<?php

namespace App\Custom;

trait Fillable
{
    public function fill(array $attributes = [])
    {
        $casts = $this->casts();
        foreach ($attributes as $attribute => $value) {
            property_exists($this, $attribute) && $this->{$attribute} = $this->castAttribute($value,$casts[$attribute]??null);
        }
    }

    /**
     * 属性的转换规则
     * @return array
     */
    public function casts() :array
    {
        return [];
    }

    /**
     * 转换类型
     * @param $value
     * @param string|null $type
     * @return bool|float|int|mixed|string
     */
    public function castAttribute($value, ?string $type)
    {
        if (is_null($value) || is_null($type)) {
            return $value;
        }
        switch ($type) {
            case 'integer':
                $value = (int) $value;
                break;
            case 'float':
                $value = (float) $value;
                break;
            case 'boolean':
                $value = (bool) $value;
                break;
            case 'array':
                $value = (array) $value;
            // no break
            case 'json':
                $option = !empty($param) ? (int) $param : JSON_UNESCAPED_UNICODE;
                $value  = json_encode($value, $option);
                break;
            case 'object':
                if (is_object($value)) {
                    $value = json_encode($value, JSON_FORCE_OBJECT);
                }
                break;
            case 'serialize':
                $value = serialize($value);
                break;
            default:
                if (is_object($value) && false !== strpos($type, '\\') && method_exists($value, '__toString')) {
                    // 对象类型
                    $value = $value->__toString();
                }
        }
        return $value;
    }
}